package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import java.util.*;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.context.ConstantCollectionHandler;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.context.FlowElementProcessContext;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.UserTaskActivityProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.MultiInstanceTaskCompleteListener;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl.task.MultiInstanceTaskCreateListener;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.ExpressionUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ConstanceVariable;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.MultiInstanceKeyEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.enums.TaskCompletedKeyEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.FormInstanceDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.Activity;
import org.flowable.bpmn.model.CollectionHandler;
import org.flowable.bpmn.model.FlowableListener;
import org.flowable.bpmn.model.ImplementationType;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.delegate.BaseTaskListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author lilh
 * @date 2020/11/17 11:19
 */
@Service
public class MultiInstanceUserTaskActivityProcessor implements UserTaskActivityProcessor {

    @Autowired
    private FlowReModelCustomConfigRepository flowReModelCustomConfigRepository;

    @Autowired
    private FlowModelVariableRepository flowModelVariableRepository;

    @Autowired
    private FlowParticipantRepository flowParticipantRepository;

    @Override
    public boolean support(UserTask userTask) {
        return userTask.hasMultiInstanceLoopCharacteristics();
    }

    @Override
    public void process(FlowElementProcessContext context) {
        UserTask userTask = (UserTask) context.getActivity();
        //会签任务
        userTask.getLoopCharacteristics().setCollectionString(resolveUsersAndGroups(userTask));

        //1.设置会签变量及assignee变量
        resolveUserTaskBaseInfo(userTask);

        //2.清空candidateUser和group
        cleanCandidateUsersAndGroups(userTask);

        //3.设置办理人处理器
        resolveCollectionHandler(userTask);

        //4.设置任务监听器
        resolveTaskListener(userTask);

        //5.保存一票否决的配置
        resolveOneVoteVeto(context);

        //6、保存会签完成条件、设置会签节点结束的监听器
        resolveSignCompleteHandler(userTask,context);
    }

    private void resolveOneVoteVeto(FlowElementProcessContext context) {
        JsonNode jsonNode = context.getElementNode();
        JsonNode properties = jsonNode.get("properties");
        if (Objects.nonNull(properties)){
            JsonNode oneVoteVetoTypeJsonNode = properties.get(MultiInstanceKeyEnum.ONE_VOTE_VETO_TYPE.getCode());
            if (Objects.nonNull(oneVoteVetoTypeJsonNode)){
                String oneVoteVetoTypeValue = oneVoteVetoTypeJsonNode.toString();
                OneVoteVetoType oneVoteVetoType = new OneVoteVetoType();
                oneVoteVetoType.setDeploymentId(context.getDeployId());
                oneVoteVetoType.setNodeCode(context.getNodeCode());
                oneVoteVetoType.setValue(oneVoteVetoTypeValue);
                oneVoteVetoType.save();
            }
        }
    }


    private void resolveSignCompleteHandler(UserTask userTask,FlowElementProcessContext context) {

        String completionConditionStr = userTask.getLoopCharacteristics().getCompletionCondition();
        //保存节点完成情况表达式
        //默认
        CompletionCondition completionCondition = new CompletionCondition();
        completionCondition.setDeploymentId(context.getDeployId());
        completionCondition.setNodeCode(context.getNodeCode());
        completionCondition.setValue(completionConditionStr);
        completionCondition.save();
        userTask.getLoopCharacteristics().setCompletionCondition("${multiInstanceCompleteHandler.accessCondition(execution)}");
    }


    private String resolveUsersAndGroups(UserTask userTask) {
        Map<String, String> result = new HashMap<>(2);
        List<String> candidateUsers = userTask.getCandidateUsers();
        for (String candidateUser : candidateUsers) {
            JSONObject jsonObject = JSONObject.parseObject(candidateUser);

            String type = jsonObject.getString("type");
            String value = jsonObject.getString("value");
            if (Objects.equals("VAR",type)){
                type = jsonObject.getString("varType");
            }
            if (StringUtils.isEmpty(type)){
                type = "STA";
            }
            putToMap(type.toLowerCase(),value,result);
        }
        return JSONObject.toJSONString(result);
    }

    private void putToMap(String type,String value,Map<String,String> param){
        String candidate = param.get(type);
        if (StringUtils.isNotBlank(candidate)){
            candidate +=","+value;
        }else{
            candidate = value;
        }
        param.put(type,candidate);
    }

    private void resolveUserTaskBaseInfo(UserTask activity) {
        activity.getLoopCharacteristics().setElementVariable("assignee");
        activity.getLoopCharacteristics().setLoopCardinality(null);
        activity.getLoopCharacteristics().setInputDataItem("");
        activity.setAssignee("${assignee}");
    }

    private void cleanCandidateUsersAndGroups(UserTask activity) {
        activity.setCandidateUsers(Collections.emptyList());
        activity.setCandidateGroups(Collections.emptyList());
    }

    private void resolveCollectionHandler(Activity activity) {
        CollectionHandler collectionHandler = new CollectionHandler();
        collectionHandler.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
        collectionHandler.setImplementation(ConstantCollectionHandler.class.getCanonicalName());
        activity.getLoopCharacteristics().setHandler(collectionHandler);
    }

    private void resolveTaskListener(UserTask activity) {
        resolveTaskListener(activity, BaseTaskListener.EVENTNAME_COMPLETE, MultiInstanceTaskCompleteListener.class.getCanonicalName());
        resolveTaskListener(activity, BaseTaskListener.EVENTNAME_CREATE, MultiInstanceTaskCreateListener.class.getCanonicalName());
    }

    private void resolveTaskListener(UserTask activity, String event, String implement) {
        FlowableListener completeListener = new FlowableListener();
        completeListener.setEvent(event);
        completeListener.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_CLASS);
        completeListener.setImplementation(implement);
        activity.getTaskListeners().add(completeListener);
    }
}
